package net.dreamlu.kit;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.util.List;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;
import org.mozilla.javascript.ErrorReporter;
import org.mozilla.javascript.EvaluatorException;

import com.google.common.collect.Lists;
import com.jfinal.kit.PathKit;
import com.yahoo.platform.yui.compressor.CssCompressor;
import com.yahoo.platform.yui.compressor.JavaScriptCompressor;

/**
 * YUICompressor压缩帮助类
 * @author L.cm
 * @date 2013-7-1 下午1:00:28
 */
public class AssetsKit {

    private static final Logger log = Logger.getLogger(AssetsKit.class);
    public static final String CHARSET = "UTF-8";
    public static final String JS_EXT = ".js", CSS_EXT = ".css";

    /**
     * 压缩css,js
     * @param queryString
     * @param isCss
     * @param out
     * @return
     */
    public static boolean compressorHelper(List<String> fileList, boolean isCss, Writer out) {
        Reader in = null;
        try {
            if (isCss) {
                for (String path : fileList) {
                    in = new InputStreamReader(new FileInputStream(path), CHARSET);
                    if(path.indexOf(".min.") > 0){// 对.min.css的css放弃压缩
                        out.append(IOKit.readerToString(in));
                    }else{
                        CssCompressor css = new CssCompressor(in);
                        in.close(); in = null;
                        css.compress(out, -1);
                    }
                }
            }else{
                // nomunge: 混淆,verbose：显示信息消息和警告,preserveAllSemiColons：保留所有的分号 ,disableOptimizations 禁止优化
                boolean munge = true, verbose = false, preserveAllSemiColons = false, disableOptimizations = false;
                for (String path : fileList) {
                    in = new InputStreamReader(new FileInputStream(path), CHARSET);
                    if(path.indexOf(".min.") > 0){ // 对.min.js的js放弃压缩
                        out.append(IOKit.readerToString(in));
                    }else{
                        JavaScriptCompressor compressor = new JavaScriptCompressor(in, new ErrorReporter() {
                            public void warning(String message, String sourceName,
                                  int line, String lineSource, int lineOffset) {
                                if (line < 0) {
                                    log.error("\n[WARNING] " + message);
                                } else {
                                    log.error("\n[WARNING] " + line + ':' + lineOffset + ':' + message);
                                }
                            }
                            public void error(String message, String sourceName,
                                  int line, String lineSource, int lineOffset) {
                                if (line < 0) {
                                    log.error("\n[ERROR] " + message);
                                } else {
                                    log.error("\n[ERROR] " + line + ':' + lineOffset + ':' + message);
                                }
                            }
                            public EvaluatorException runtimeError(String message, String sourceName,
                                  int line, String lineSource, int lineOffset) {
                                error(message, sourceName, line, lineSource, lineOffset);
                                return new EvaluatorException(message);
                            }
                        });
                        in.close(); in = null;
                        compressor.compress(out, -1, munge, verbose, preserveAllSemiColons, disableOptimizations);
                    }
                }
            }
            out.flush();
            return true;
        }catch(IOException e){
            e.printStackTrace();
            log.error(e);
            return false;
        }finally{
            IOUtils.closeQuietly(in);
            IOUtils.closeQuietly(out);
        }
    }
    
    @SuppressWarnings("unchecked")
    public static String combo(String fileName) {
//         String fileName = "/assets/assets-web.jcss";
//         String fileName = "/assets/assets-web.jjs";
        String rootPath = PathKit.getWebRootPath();
        String comboName = fileName.substring(0, fileName.indexOf(".")); // /assets/assets-web
        
        Writer out = null;
        try {
            // 读取文件中的js或者css路径
            List<String> list = FileUtils.readLines(new File(rootPath + fileName), CHARSET);
             List<String> comboList = Lists.newArrayList(); // 文件路基
             StringBuilder sb = new StringBuilder(); // 文件内容
             for (String string : list) {
                 if (string.startsWith("@")) {
                     comboList.add(PathKit.getWebRootPath() + string.substring(1, string.length()));
                 }
                 sb.append(string);
             }
            // 文件内容hex
             String hex = DigestUtils.md5Hex(sb.toString()); // 为了方便没有md5整个文件集
             
             boolean isCss = true;
             if (fileName.endsWith(".jjs")) {
                 isCss = false;
             }
             
             String newFileName = comboName + "-"  + hex + (isCss ? CSS_EXT : JS_EXT);
             
             String newPath = rootPath + newFileName;
             File file = new File(newPath);
             
             boolean temp = file.exists();
             if (temp) {
                 return newFileName;
             }
         
            out  = new OutputStreamWriter(new FileOutputStream(newPath), CHARSET);
            compressorHelper(comboList, isCss, out);
            
            return newFileName;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            IOUtils.closeQuietly(out);
        }
        return null;
    }
    
    public static void main(String[] args) throws IOException {
        long aa = System.currentTimeMillis();
//        String fileName = "/assets/assets-web.jcss";
        String fileName = "/assets/assets-web.jjs";
        
        System.out.println(combo(fileName));
        long bb = System.currentTimeMillis();
        System.out.println(bb - aa);
    }
}